package com.bestvike.stone.spring.rest;

import com.bestvike.stone.core.lang.BeanUtils;
import com.bestvike.stone.core.serialization.fastjson.StringObjectMapDeserializer;
import com.bestvike.stone.spring.exception.BusinessException;
import com.bestvike.stone.spring.exception.ErrorCode;
import com.bestvike.stone.spring.rest.common.CommonResponse;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Objects;

/**
 * Created by 许崇雷 on 2017-10-08.
 */
public interface IResponse<TBody> {
    static <TBody> TBody getBodyOfMap(Map response, Type responseType) {
        if (responseType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) responseType;
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            if (actualTypeArguments.length > 0)
                return BeanUtils.toBean(response, actualTypeArguments[0]);
        }

        throw new RuntimeException("字段 type 的值无效, 参见:" + StringObjectMapDeserializer.class.getName());
    }

    String getCode();

    String getMsg();

    TBody getBody();

    default IResponse<TBody> toCommonResponse() {
        if (this instanceof CommonResponse)
            return this;
        CommonResponse<TBody> response = CommonResponse.create(this.getCode(), this.getMsg());
        response.setBody(this.getBody());
        return response;
    }

    default boolean isSuccess(boolean needBody) {
        String code = this.getCode();
        boolean isSuccess = Objects.equals(code, ErrorCode.SUCCESS.getCode());
        return needBody ? isSuccess && this.getBody() != null : isSuccess;
    }

    default boolean isSuccess() {
        return this.isSuccess(false);
    }

    default boolean isSuccessNeedBody() {
        return this.isSuccess(true);
    }

    default void assertSuccess(boolean needBody) {
        if (this.isSuccess(needBody))
            return;
        throw new BusinessException(this.getCode(), this.getMsg());
    }

    default void assertSuccess() {
        this.assertSuccess(false);
    }

    default void assertSuccessNeedBody() {
        this.assertSuccess(true);
    }
}
